#include "Includes.h"

using namespace std;


struct MyEx: exception {
public: 
	string what;
	MyEx (string s) {
		what = s;
	}
};

/*
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
trololo svn
*/

double metric(CBlob* a, CBlob* b) {
	double xa,ya,xb,yb;
	xa = (a->MaxX() + a->MinX())/2;
	ya = (a->MaxY() + a->MinY())/2;
	xb = (b->MaxX() + b->MinX())/2;
	yb = (b->MaxY() + b->MinY())/2;
	return sqrt( (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
}

IplImage* bernsen(IplImage* img, int block_size, bool invert, double divider){
	IplImage *tmp = cvCreateImage( cvSize(img->width,img->height), img->depth, img->nChannels);
	uchar max=0,min=0,threshold=0;
	for( int y = block_size/2; y < img->height-(block_size/2); y++ ) {
		for( int x = block_size/2; x < img->width-(block_size/2); x++ ) {
			for(int j=-(block_size/2);j<block_size/2;j++){
				for(int i=-(block_size/2);i<block_size/2;i++){
					max = max<(uchar)(img->imageData[(y+j) * img->widthStep+x+i] )?
						(uchar)(img->imageData[(y+j) * img->widthStep+x+i] ):max;
					min = min>(uchar)(img->imageData[(y+j) * img->widthStep+x+i] )?
						(uchar)(img->imageData[(y+j) * img->widthStep+x+i] ):min;
				}
			}
			threshold = (max+min)/divider;
			(tmp->imageData[y * tmp->widthStep+x] ) = 
				(uchar)(img->imageData[y * img->widthStep+x] )<=threshold?(uchar)(invert? 255: 0):(uchar)(invert? 0: 255);
		}
	}
	return tmp;
}

IplImage* rotateImage(IplImage *src, float angle)
{
	CvPoint2D32f centre;
	IplImage *dst = cvCreateImage( cvSize(src->width, src->height), src->depth, src->nChannels);
	CvMat *translate = cvCreateMat(2, 3, CV_32FC1);
	cvSetZero(translate);
	centre.x = src->width/2;
	centre.y = src->height/2;
	cv2DRotationMatrix(centre, angle, 1.0, translate);
	cvWarpAffine(src, dst, translate, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
	cvReleaseMat(&translate);
	return dst;
}

int VerticalLine(IplImage* img, int x) {
	int sum = 0;
	for (int y = img->height-1; y >= 0; y--) {
		if (img->imageData[img->widthStep*y + x] == 0) sum++;
	}
	return sum;
}

int HorizontalLine(IplImage* img, int y) {
	int sum = 0;
	for (int x = img->width-1; x >= 0; x--) {
		if (img->imageData[img->widthStep*y + x] == 0) sum++;
	}
	return sum;
}

int FindSymbolLine(IplImage* img, int beginpos) {
	if(beginpos > img->width - 2) return beginpos;
	while(VerticalLine(img, beginpos) < 5 && beginpos < (img->width-1) ) beginpos++;
	return beginpos;
}

int FindClearLine(IplImage* img, int beginpos, int xbegin) {
	if(beginpos > img->width - 2) return beginpos;
	while(VerticalLine(img, beginpos)>2 && beginpos < (img->width-1) ) beginpos++;
	if (VerticalLine(img, beginpos+1) < 1 && (beginpos-xbegin) > 18) return beginpos;
	else return FindClearLine(img, beginpos+1, xbegin);
}

bool HasClearTop(IplImage* img, int threshold) {
	int sum = 0;
	for (int x = 0; x < img->width; x++) {
		if (img->imageData[img->widthStep + x] == 0) sum++;
	}
	if (sum < threshold) return true;
	return false;
}

bool HasClearLeft(IplImage* img) {
	for (int y = 0; y < img->height; y++) {
		if (img->imageData[img->widthStep*y] == 0) return false;
	}
	return true;
}

bool HasClearRight(IplImage* img) {
	for (int y = 0; y < img->height; y++) {
		if (img->imageData[img->widthStep*y + img->width - 1] == 0) return false;
	}
	return true;
}

bool ClearVerticalLine(IplImage* img, int x) {
	int sum = 0;
	for (int y = img->height - 1; y >= 0; y--) {
		if (img->imageData[img->widthStep*y + x] == 0) sum++;
	}
	if (sum < 2) return true;
	else return false;
}

bool ClearHorizontalRange(IplImage* img, int y, int x1, int x2) {
	int sum = 0;
	for (int x = x1; x <= x2; x++) {
		if (img->imageData[img->widthStep*y + x] == 0) sum++;
	}
	if (sum < 2) return true;
	else return false;
}

bool ClearVerticalRange(IplImage* img, int x, int y1, int y2) {
	int sum = 0;
	for (int y = y1; y <= y2; y++) {
		if (img->imageData[img->widthStep*y + x] == 0) sum++;
	}
	if (sum < 2) return true;
	else return false;
}



void FlushVerticalLine(IplImage* img, int x) {
	for (int y = img->height-1; y >= 0; y--) {
		img->imageData[img->widthStep*y + x] = 255;
	}
}

void FlushHorizontalLine(IplImage* img, int y) {
	for (int x = img->width-1; x >= 0; x--) {
		img->imageData[img->widthStep*y + x] = 255;
	}
}

/*void FlushVertically(IplImage* img) {
	int n = 0, sum = 0;
	for(int i = 0; i < img->width; i++) {
		int a = VerticalLine(img, i);
		sum += a;
		if(a > 0) n++;
	}
	double avg = sum/n;
	for(int i = 0; i < img->width; i++) {
		int a = VerticalLine(img, i);
		if( (a>3*avg)||(a<0.3*avg) ) FlushVerticalLine(img, i);
	}
}

void FlushHorizontally(IplImage* img) {
	int n = 0, sum = 0;
	for(int i = 0; i < img->height; i++) {
		int a = HorizontalLine(img, i);
		sum += a;
		if(a > 0) n++;
	}
	double avg = sum/n;
	for(int i = 0; i < img->height; i++) {
		int a = HorizontalLine(img, i);
		if( (a>3*avg)||(a<0.3*avg) ) FlushHorizontalLine(img, i);
	}
}*/
